package com.example.xiaosen.config;

import com.example.xiaosen.constants.SystemConstants;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.embedding.TokenCountBatchingStrategy;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

/**
 * @Author: zhouxj@ferrotec.com.cn
 * @version: v1.0
 * @Date: 2025/5/13 10:40
 * @Description:
 */
@Configuration
public class CommonConfiguration {

    /**
     * 注册SpringAI 聊天客户端Bean
     * @param chatModel
     * @return
     */
    @Bean
    public ChatClient chatClient(OpenAiChatModel chatModel, ChatMemory chatMemory){
        return ChatClient.builder(chatModel)
                // 使用提供视觉识别的多模态模型
                // 只有ToolCallingChatOptions配置支持MCP和工具调用，开启OpenAi模型后OpenAiChatOptions就是它的子类
                .defaultOptions(OpenAiChatOptions.builder().model("doubao-1.5-vision-pro-250328").build())
                // 默认系统角色提示词
//                .defaultSystem("你是一个江苏大学的人工智能助手，帮助同学们解答学习、就业中遇到的各种问题")
                /* SpringAI 基于AOP实现提示词增强、拦截、修改等功能，可以通过添加增强通知实现日志记录、RAG、会话记忆等功能
                 * 这里注册的SimpleLoggerAdvisor是一个简单的日志记录增强通知，便于调试输出具体的提示词内容，此外还有
                 * MessageChatMemoryAdvisor：会话记忆的Advisor
                 * QuestionAnswerAdvisor：实现RAG的Advisor
                 */
                .defaultAdvisors(new SimpleLoggerAdvisor(), MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
    }

    /**
     * 注册SpringAI 纯Prompt开发小游戏客户端Bean
     * @param chatModel
     * @param chatMemory
     * @return
     */
    @Bean
    public ChatClient gameClient(OpenAiChatModel chatModel, ChatMemory chatMemory){
        return ChatClient.builder(chatModel)
                .defaultSystem(SystemConstants.GAME_SYSTEM_PROMPT)
                .defaultAdvisors(new SimpleLoggerAdvisor(), MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
    }

    /**
     * 注册SpringAI 基于Function Call实现ai选课助手客户端Bean
     * @param chatModel
     * @param chatMemory
     * @return
     */
    @Bean
    public ChatClient agentClient(OpenAiChatModel chatModel, ChatMemory chatMemory){
        return ChatClient.builder(chatModel)
                .defaultSystem(SystemConstants.AGENT_SYSTEM_PROMPT)
                .defaultAdvisors(new SimpleLoggerAdvisor(), MessageChatMemoryAdvisor.builder(chatMemory).build())
                .build();
    }

    @Bean
    public ChatClient pdfChatClient(OpenAiChatModel chatModel, ChatMemory chatMemory, VectorStore vectorStore){
        return ChatClient.builder(chatModel)
                .defaultSystem("请根据提供的上下文回答问题，不要自己猜测。")
                .defaultAdvisors(new SimpleLoggerAdvisor()
                        , MessageChatMemoryAdvisor.builder(chatMemory).build()
                        // 早期rag通知方法
//                        , QuestionAnswerAdvisor.builder(vectorStore)
//                                .searchRequest( // 向量检索的请求参数
//                                        SearchRequest.builder()
//                                                // 相似度阈值
//                                                .similarityThreshold(0.5d)
//                                                // 返回的文档片段数量
//                                                .topK(5)
//                                                .build()
//                                ).build()
                )
                .build();
    }


    /**
     * 配置Jedis连接池Bean
     * @return
     */
//    @Bean
//    public JedisPooled jedisPooled() {
//        return new JedisPooled("124.223.207.220", 6379);
//    }

    /**
     * 由于spring-ai提供的redis vectorStore自动装配类filterExpression使用失效，改为手动配置，在初始化索引（向量库）时，需要声明过滤字段，否则无法进行过滤
     * @param jedisPooled
     * @param embeddingModel
     * @return
     */
//    @Bean
//    public VectorStore vectorStore(JedisPooled jedisPooled, OpenAiEmbeddingModel embeddingModel){
//        return RedisVectorStore
//                .builder(jedisPooled,embeddingModel)
//                .indexName("spring_ai_index")
//                .prefix("doc:")
//                // Optional: defaults to false
//                .initializeSchema(true)
//                .metadataFields(//想要以指定字段进行过滤操作必须在初始化索引时加上这一段，如果索引已经存在必须先删除后再进行初始化。
//                        new RedisVectorStore.MetadataField("file_name", Schema.FieldType.TEXT)
//                )
//                // Optional: defaults to TokenCountBatchingStrategy
//                .batchingStrategy(new TokenCountBatchingStrategy())
//                .build();
//    }

    /**
     * 注册SpringAI 会话记忆存储实例Bean，这里使用jdbc数据库持久化
     * SpringAI通过conversationId来保存和查询会话记忆
     * @return
     */
    @Bean
    public ChatMemory chatMemory(JdbcChatMemoryRepository chatMemoryRepository){
        // 临时使用内存存储会话记忆，已弃用
//        return new InMemoryChatMemory();
        return MessageWindowChatMemory.builder()
                .chatMemoryRepository(chatMemoryRepository)
                .maxMessages(10)
                .build();
    }

}
